﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using DA = InkFx.WinControl.XIDEAlignment;
using DTGS = InkFx.WinControl.XIDETabGroupState;

namespace InkFx.WinControl
{
    public partial class XIDEFloatForm : System.Windows.Forms.Form
    {
        public XIDEFloatForm()
        {
            InitializeComponent();
            base.Padding = new Padding(PADDING);
            //base.DoubleBuffered = true; //这种需要快速弹出的窗体, 设置 双缓冲 只会减慢启动速度
            this.ShowInTaskbar = false;
        }


        #region  重 绘 美 化

        protected System.Windows.Forms.FormBorderStyle m_FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;

        public new System.Windows.Forms.FormBorderStyle FormBorderStyle
        {
            get
            {
                if (base.FormBorderStyle != System.Windows.Forms.FormBorderStyle.None)
                {
                    m_FormBorderStyle = base.FormBorderStyle;
                    base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                }
                return m_FormBorderStyle;
            }
            set
            {
                //if (base.FormBorderStyle != FormBorderStyle.None)
                base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                m_FormBorderStyle = value;
                this.Refresh();
            }
        }
        public new System.Windows.Forms.FormWindowState WindowState
        {
            get { return base.WindowState; }
            set
            {
                base.WindowState = value == FormWindowState.Minimized ? FormWindowState.Normal : value;
                this.Refresh();
            }
        }



        #region  消 息 处 理

        protected bool isPosChanged;
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            {
                //bool isMax = Win32API.IsZoomed(this.Handle) || WindowState == FormWindowState.Maximized;
                switch (m.Msg)
                {
                    case Win32Msg.WM_NCHITTEST:
                        #region  WM_NCHITTEST
                        {
                            SkinFormOffset offset = new SkinFormOffset(XIDETabGroup.CAPTION_HEIGHT + 1, PADDING + 1, PADDING + 1, PADDING + 1, PADDING + 1, PADDING + 1);
                            Point screenPoint = new Point((int)m.LParam & 0xFFFF, (int)m.LParam >> 16 & 0xFFFF);
                            Point formPoint = ScreenPointToForm(screenPoint);

                            #region  标题栏拖动窗体

                            if (offset.CaptionAndTopSize > 0)
                            {
                                if (true
                                    && (formPoint.X > offset.Border && formPoint.X < this.Width - offset.Border)
                                    && (formPoint.Y > offset.Border && formPoint.Y < offset.CaptionAndTopSize))
                                {
                                    m.Result = (IntPtr)Win32Msg.HTCAPTION; //标题栏拖动
                                    break;
                                }
                            }

                            #endregion

                            #region  边框拖动尺寸

                            if (offset.Border > 0)
                            {
                                if (formPoint.X <= offset.Border)
                                    if (formPoint.Y <= offset.Border) { m.Result = (IntPtr)HitTest.HTTOPLEFT; break; }
                                    else if (formPoint.Y >= this.Height - offset.Border) { m.Result = (IntPtr)HitTest.HTBOTTOMLEFT; break; }
                                    else { m.Result = (IntPtr)HitTest.HTLEFT; break; }
                                else if (formPoint.X >= this.Width - offset.Border)
                                    if (formPoint.Y <= offset.Border) { m.Result = (IntPtr)HitTest.HTTOPRIGHT; break; }
                                    else if (formPoint.Y >= this.Height - offset.Border) { m.Result = (IntPtr)HitTest.HTBOTTOMRIGHT; break; }
                                    else { m.Result = (IntPtr)HitTest.HTRIGHT; break; }
                                else if (formPoint.Y <= offset.Border) { m.Result = (IntPtr)HitTest.HTTOP; break; }
                                else if (formPoint.Y >= this.Height - offset.Border) { m.Result = (IntPtr)HitTest.HTBOTTOM; break; }
                            }

                            #endregion


                            base.WndProc(ref m);
                            m.Result = (IntPtr)HitTest.HTCLIENT; //剩下的全都是 客户区
                            break;
                        }
                        #endregion
                    case Win32Msg.WM_NCPAINT:
                        #region  WM_NCPAINT
                        SetFormShadow();
                        base.WndProc(ref m);
                        break;
                        #endregion
                    case Win32Msg.WM_WINDOWPOSCHANGED:
                        #region  WM_WINDOWPOSCHANGED
                        isPosChanged = true;
                        base.WndProc(ref m);
                        isPosChanged = false;
                        break;
                        #endregion
                    case Win32Msg.WM_NCCALCSIZE:
                        break;
                    case Win32Msg.WM_GETMINMAXINFO:
                        #region  WM_GETMINMAXINFO
                        {
                            bool isNone = this.FormBorderStyle == System.Windows.Forms.FormBorderStyle.None;
                            Rectangle rectWork = System.Windows.Forms.Screen.GetWorkingArea(this);
                            MINMAXINFO minmax = (MINMAXINFO)m.GetLParam(typeof(MINMAXINFO));

                            SkinFormOffset offset = new SkinFormOffset(XIDETabGroup.CAPTION_HEIGHT + 1, PADDING + 1, PADDING + 1, PADDING + 1, PADDING + 1, PADDING + 1);
                            int leftSize = isNone ? 0 : offset.LeftSize;
                            int rightSize = isNone ? 0 : offset.RightSize;
                            int topSize = isNone ? 0 : offset.TopSize;
                            int bottomSize = isNone ? 0 : offset.BottomSize;
                            //int leftSize = offset.LeftSize;
                            //int rightSize = offset.RightSize;
                            //int topSize = offset.TopSize;
                            //int bottomSize = offset.BottomSize;

                            minmax.maxPosition.X = 0 - leftSize;
                            minmax.maxPosition.Y = 0 - topSize;
                            minmax.maxSize.Width = rectWork.Width + leftSize + rightSize;
                            minmax.maxSize.Height = rectWork.Height + topSize + bottomSize;

                            minmax.minTrackSize = MinimumSize != Size.Empty ? MinimumSize : new Size(140, XIDETabGroup.CAPTION_HEIGHT * 2 + offset.TopSize + offset.BottomSize + 2);
                            Marshal.StructureToPtr(minmax, m.LParam, true);
                            m.Result = Win32API.IntPtrFlase;

                            break;
                        }
                        #endregion
                    case Win32Msg.WM_NCACTIVATE:
                        #region  WM_NCACTIVATE
                        DrawNonClient(m.WParam.ToInt32() > 0);
                        m.Result = Win32API.IntPtrTrue;
                        break;
                        #endregion
                    default:
                        base.WndProc(ref m);
                        break;
                }
            }
        }

        /// <summary>
        /// 设置窗体边框阴影 (仅支持 Win7+ 系统, 且 窗体不能是圆角, 本函数才会生效)
        /// </summary>
        protected virtual void SetFormShadow()
        {
            if (!Form.IsDesignMode && Win32API.EnableAero)
            {
                int v = 2;
                Win32API.DwmSetWindowAttribute(this.Handle, 2, ref v, 4);
                Win32API.MARGINS margins = new Win32API.MARGINS { bottomHeight = 1, leftWidth = 1, rightWidth = 1, topHeight = 1 };
                Win32API.DwmExtendFrameIntoClientArea(this.Handle, ref margins);
            }
        }
        /// <summary>
        /// 鼠标的屏幕坐标 转换成 窗体坐标 (包括 客户区 和 非客户区)
        /// </summary>
        public Point ScreenPointToForm(Point screenPoint)
        {
            Point location = this.Location;
            return new Point(screenPoint.X - location.X, screenPoint.Y - location.Y);
        }

        /// <summary>
        /// 执行非客户区重绘
        /// </summary>
        public void DrawNonClient(bool active)
        {
        }


        #endregion



        #endregion



        #region  IDEPanel 相 关

        public static XIDEFloatForm ShowControl(XIDEPanel idePanel, XIDETabGroup group, Rectangle rect)
        {
            XIDEPopPanel.TogglePopGroup(null);

            XIDEFloatForm form = new XIDEFloatForm();
            form.TabGroup = group;
            form.IDEPanel = idePanel;
            form.Font = idePanel.Font;

            if (rect != Rectangle.Empty)
            {
                form.StartPosition = FormStartPosition.Manual;
                form.Bounds = rect;
            }

            group.Dock = DockStyle.Fill;
            group.State = DTGS.Float;
            group.Parent = form;
            form.Show(idePanel.FindForm());
            group.Focus();

            //idePanel.DoLayout();
            idePanel.Invalidate();
            return form;
        }



        private List<XIDETipForm> m_ListTipForm = new List<XIDETipForm>();

        public const int PADDING = 3;
        public XIDETabGroup TabGroup { get; private set; }
        public XIDEPanel IDEPanel { get; private set; }


        public void ShowTipForm()
        {
            var idePanel = IDEPanel;
            if (idePanel == null || idePanel.Disposing || idePanel.IsDisposed) return;

            var list1 = new List<System.Windows.Forms.Control>();
            var list2 = new List<System.Windows.Forms.Control>();
            list1.Add(idePanel);
            if (idePanel.CenterPanel != null) list1.Add(idePanel.CenterPanel);

            var list9 = idePanel.GetListTabGroup();
            if (list9 != null)
            {
                var curr = this.TabGroup;
                var list4 = new List<XIDETabGroup>(list9);
                foreach (var group in list4)
                {
                    if (group == curr || !ShowIDETipForm(group)) continue;
                    list1.Add(group);
                }
            }

            var point = System.Windows.Forms.Control.MousePosition;
            foreach (var ctrl in list1)
            {
                var rect = Win32API.GetWindowRectangle(ctrl.Handle);
                if (rect.Contains(point)) { list2.Add(ctrl); }
            }

            var list3 = new List<XIDETipForm>(m_ListTipForm);
            foreach (var ctrl in list2)
            {
                var temp = ctrl;
                XIDETipForm form = m_ListTipForm.Find(x => x.Control == temp);
                if (form != null) { list3.Remove(form); form.Invalidate(); }
                else
                {
                    form = XIDETipForm.ShowTipForm(idePanel, ctrl, this);
                    if (form != null) m_ListTipForm.Add(form);
                }
            }

            foreach (var form in list3)
            {
                form.Dispose();
                m_ListTipForm.Remove(form);
            }
        }
        public void HideTipForm()
        {
            if (m_ListTipForm != null)
            {
                foreach (var form2 in m_ListTipForm) { form2.Dispose(); }
                m_ListTipForm.Clear();
            }
        }




        private bool ShowIDETipForm(XIDETabGroup group)
        {
            if (group == null) return false;
            bool hide = !group.Visible || (group == this.TabGroup) || (group.State != DTGS.Expand && group.State != DTGS.Float && group.State != DTGS.Popup);
            if (hide) return false;

            //var handle = this.Handle;
            //var rect = Win32API.GetWindowRectangle(handle);
            //if (handle != Win32API.WindowFromPoint(new Point(rect.X + 1, rect.Y + 1))) return false;
            //if (handle != Win32API.WindowFromPoint(new Point(rect.X + rect.Width - 1, rect.Y + 1))) return false;
            //if (handle != Win32API.WindowFromPoint(new Point(rect.X + 1, rect.Y + rect.Height - 1))) return false;
            //if (handle != Win32API.WindowFromPoint(new Point(rect.X + rect.Width - 1, rect.Y + rect.Height - 1))) return false;
            
            return true;
        }
        public XIDEEventArgs NewIDEEventArgs()
        {
            if (m_ListTipForm == null || m_ListTipForm.Count <= 0) return null;

            foreach (var form in m_ListTipForm)
            {
                var e = form.NewIDEEventArgs();
                if (e != null) { return e; }
            }
            return null;
        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            base.DoubleBuffered = true;
        }
        protected override void OnLocationChanged(EventArgs e)
        {
            base.OnLocationChanged(e);

            if (MouseButtons == MouseButtons.Left) this.ShowTipForm();
        }
        protected override void OnControlRemoved(ControlEventArgs e)
        {
            base.OnControlRemoved(e);

            XIDETabGroup group = null;
            foreach (var ctrl in this.Controls)
                if (ctrl is XIDETabGroup) { group = (XIDETabGroup)ctrl; break; }

            if (group != null) { this.TabGroup = group; }
            else { Dispose(); }
        }

        #endregion



        public virtual new void Dispose()
        {
            HideTipForm();

            var group = this.TabGroup;
            var form = group == null ? null : group.FindForm();
            if (form == this) group.Parent = null;

            TabGroup = null;
            IDEPanel = null;
            if (!this.Disposing && !this.IsDisposed) { this.Close(); base.Dispose(); }
        }
    }


}
